from typing import List
from PyQt5.QtGui import QPainter, QPaintEvent, QColor, QPen, QMouseEvent
from PyQt5.QtWidgets import QWidget, QDialog
from PyQt5.QtCore import Qt, QRectF, QLine, QPointF, QPoint
from Plugin.CurveAdjustment.curves_design import Ui_CurveAdjustmentWidget
import time

import cv2
import numpy as np

import Processor.Converter as Converter


class CurveController(QDialog, Ui_CurveAdjustmentWidget):
    layer = None  # 图层
    mat = None  # 原始Mat 数据
    matChannel = None  # 通道RGB数据
    titleChangeFlag = False  # 控制titleSize spinBox数值变化 避免死循环

    def __init__(self, parent, mat=None):
        super().__init__(parent)
        self.setupUi(self)
        self.CurveCanvas.dialog = self
        self.initUI(parent)
        self.mat = mat
        self.matChannel = mat.copy()

    def initUI(self, parent):
        self.setWindowTitle('曲线控制器')
        self.setAttribute(Qt.WA_DeleteOnClose, True)
        # 定位
        self.resize(300, 400)
        pos = parent.geometry()
        self.move((pos.width() - self.width()) / 2, (pos.height() - self.height()) / 2)
        #       信号
        # 确定
        self.DialogButtonBox.accepted.connect(self.accept)
        self.DialogButtonBox.rejected.connect(self.reject)
        # 通道切换
        self.comboBox_channel.currentIndexChanged.connect(self.comboBox_channel_slot)

    def reject(self):
        """
        取消操作
        :return:
        """
        image = Converter.Numpy2QImage(self.mat)
        self.layer.updatePixmap(image)
        QDialog.reject(self)

    def comboBox_channel_slot(self):
        self.CurveCanvas.changeChanel(self.comboBox_channel.currentIndex())

    def updateChannelData(self):
        start = time.perf_counter()
        # 更新当前通道灰度数据
        channel = self.comboBox_channel.currentIndex()
        if channel > 0:
            curveData = self.CurveCanvas.curveDataList[channel]
            channel = channel - 1
            self.matChannel[:, :, channel] = cv2.LUT(self.mat[:, :, channel], curveData)
        self.updateSlot()
        end = time.perf_counter()
        print('curve adjustment 耗时:', end - start)

    def updateSlot(self):
        curveData = self.CurveCanvas.curveDataList[0]
        image = self.matChannel.copy()
        if curveData is not None:
            print(curveData.shape)
            image[:, :, 0:3] = cv2.LUT(image[:, :, 0:3], curveData)
        image = Converter.Numpy2QImage(image)
        self.layer.updatePixmap(image)

    def __histogram(self, channel=0, bin=256):
        """
        生成直方图
        :param channel: 0 全部， 1 R, 2 G, 3 B
        :param bin: 组合数大小，分辨率
        :return: 归一化的nx1 矩阵（归一化到最大值）
        """
        start = time.perf_counter()
        if channel == 0:
            mat = self.grayMat
        else:
            mat = self.mat
            channel = channel - 1
        hist = cv2.calcHist([mat], [channel], None, [bin], [0, 256])
        end = time.perf_counter()
        print('histogram', '耗时：', end - start)
        return hist / hist.max()    # 归一化


def newCurveAdjustment():
    """
    :param window: 主窗体
    :return:
    """
    window = Window
    layer = window.currentLayer
    if layer:
        image = layer.image  # 当前图层QImage句柄
        mat = Converter.QImage2Numpy(image)
        controller = CurveController(window, mat)
        controller.layer = layer
        if controller.exec_():
            del controller
            pass


Window = None  # 主窗体


def init(window):
    """
    初始化
    :param window: 主窗体
    :return:
    """
    global Window
    Window = window
    __menu()    # 创建菜单栏


def __menu():
    """
    将插件入口连接到菜单栏，这样，点击菜单栏按钮时，能使用本插件功能
    :return:
    """
    window = Window
    menuBar = window.menuBar()    # 菜单栏句柄
    menu_layer = menuBar.menu_layer   # 图层栏句柄
    menu_adjustment = menu_layer.menu_adjustment
    action = menuBar.newAction('曲线调整', menuBar)  # 新建菜单栏选项
    action.func = newCurveAdjustment   # 当按钮出发时，运行 newBlur 方法
    menu_adjustment.addAction(action)   # 把选项添加到 滤波 分类